<template>
	<div class="card content-box">
		<div id="container"></div>
	</div>
</template>
 
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { Graph, Dom, Node, Cell } from "@antv/x6";
import dagre from "dagre";
 
let graph = ref();
// 自定义节点（多种方式）wq
Graph.registerNode(
	"org-node", // 自定义节点名
	{
		width: 180,
		height: 80,
		attrs: {
			body: {
				width: 180,
				height: 80,
				rx: 4, // 圆角矩形
				ry: 4,
				strokeWidth: 0,
				fill: "#ffd591"
				// stroke: "#ffd591"
			},
			// image: {
			// 	"xlink:href": "https://gw.alipayobjects.com/zos/antfincdn/FLrTNDvlna/antv.png",
			// 	width: 16,
			// 	height: 16,
			// 	x: 12,
			// 	y: 12
			// },
			title: {
				refX: 10,
				refY: 15,
				fill: "rgba(0,0,0,0.85)",
				fontSize: 15,
				fontWeight: 800,
				"text-anchor": "start"
			},
			text: {
				refX: 10,
				refY: 35,
				fontSize: 14,
				fill: "rgba(0,0,0,0.6)",
				"text-anchor": "start"
			},
			".date": {
				refX: 10,
				refY: 55,
				fontSize: 14,
				fill: "rgba(0,0,0,0.6)",
				"text-anchor": "start"
			}
		},
		markup: [
			{
				tagName: "rect",
				selector: "body"
			},
			{
				tagName: "image",
				selector: "image"
			},
			{
				tagName: "text",
				selector: "title"
			},
			{
				tagName: "text",
				selector: "text"
			},
			{
				tagName: "text",
				attrs: {
					class: "date"
				}
			}
		]
	},
	true // 重名时是否覆盖
);
 
// 自定义边
Graph.registerEdge(
	"org-edge", // 自定义边名
	{
		zIndex: -1,
		attrs: {
			line: {
				fill: "none",
				strokeLinejoin: "round",
				strokeWidth: 2,
				stroke: "#A2B1C3"
			}
		}
	},
	true // 重名时是否覆盖
);
 
// 创建节点
const createNode = (title: string, text?: string, date?: string) => {
	return graph.value.createNode({
		shape: "org-node",
		attrs: {
			title: {
				text: Dom.breakText(title, { width: 160, height: 20 })
			},
			text: {
				text: Dom.breakText(text as string, { width: 160, height: 18 })
			},
			".date": {
				text: Dom.breakText(date as string, { width: 160, height: 18 })
			}
		}
	});
};
 
// 创建连接线
const createEdge = (source: Cell, target: Cell) => {
	return graph.value.createEdge({
		shape: "org-edge",
		source: { cell: source.id },
		target: { cell: target.id }
	});
};
 
// 自动布局
const layout = () => {
	const nodes = graph.value.getNodes();
	const edges = graph.value.getEdges();
	const g = new dagre.graphlib.Graph();
	g.setGraph({ rankdir: "TB", nodesep: 16, ranksep: 16 });
	g.setDefaultEdgeLabel(() => ({}));
 
	const width = 260;
	const height = 130;
	nodes.forEach((node: { id: any }) => {
		g.setNode(node.id, { width, height });
	});
 
	edges.forEach((edge: { getSource: () => any; getTarget: () => any }) => {
		const source = edge.getSource();
		const target = edge.getTarget();
		g.setEdge(source.cell, target.cell);
	});
 
	dagre.layout(g);
 
	// graph.value.freeze();
 
	g.nodes().forEach((id: any) => {
		const node = graph.value.getCellById(id) as Node;
		if (node) {
			const pos = g.node(id);
			node.position(pos.x, pos.y);
		}
	});
 
	edges.forEach(
		(edge: { getSourceNode: () => any; getTargetNode: () => any; setVertices: (arg0: { x: any; y: any }[]) => void }) => {
			const source = edge.getSourceNode()!;
			const target = edge.getTargetNode()!;
			const sourceBBox = source.getBBox();
			const targetBBox = target.getBBox();
 
			console.log(sourceBBox, targetBBox);
 
			const gap = targetBBox.y - sourceBBox.y - sourceBBox.height;
			const fix = sourceBBox.height;
			const y = sourceBBox.y + fix + gap / 2;
			edge.setVertices([
				{ x: sourceBBox.center.x, y },
				{ x: targetBBox.center.x, y }
			]);
		}
	);
 
	// graph.value.unfreeze();
};
 
// 挂载完成后
onMounted(() => {
	graph.value = new Graph({
		container: document.getElementById("container") as HTMLElement,
		width: 2000,
		height: 1000,
		background: {
			color: "#fffbe6" // 设置画布背景颜色
		},
		interacting: function (cellView) {
			if (cellView.cell.getData() != undefined && !cellView.cell.getData().disableMove) {
				return { nodeMovable: false };
			}
			return true;
		}
	});
 
	const nodes = [
		createNode("豫CG8999", "Pierre Omidyar"),
		createNode("人伤查勘", "Margaret", "2022-12-01 12: 12: 12"),
		createNode("标的车定损", "Scott Thompson", "2022-12-01 12: 12: 12"),
		createNode("President, Ebay Global Marketplaces", "Devin Wenig", "2022-12-01 12: 12: 12"),
		createNode("Senior Vice President Human Resources", "Jeffrey S. Skoll", "2022-12-01 12: 12: 12"),
		createNode("Senior Vice President Controller", "Steven P. Westly", "2022-12-01 12: 12: 12"),
		createNode("Senior Vice President Controller", "Steven P. Westly", "2022-12-01 12: 12: 12"),
		createNode("Senior Vice President Controller", "Steven P. Westly", "2022-12-01 12: 12: 12"),
		createNode("Senior Vice President Controller", "Steven P. Westly", "2022-12-01 12: 12: 12")
	];
 
	const edges = [
		createEdge(nodes[0], nodes[1]),
		createEdge(nodes[0], nodes[2]),
		createEdge(nodes[0], nodes[3]),
		createEdge(nodes[0], nodes[4]),
		createEdge(nodes[0], nodes[5]),
		createEdge(nodes[1], nodes[6]),
		createEdge(nodes[2], nodes[7]),
		createEdge(nodes[6], nodes[8])
	];
 
	graph.value.resetCells([...nodes, ...edges]);
	// console.log(graph.value, "21312312321");
	layout();
	graph.value.centerContent();
	// graph.value.drawBackground({ color: "#999999" }); // 创建画布后也可调用方法重绘背景
	// graph.value.drawGrid({ type: "mesh" }); // 创建画布后也可调用方法重绘画布网格
	// graph.value.zoom(0.5); // 画布和图形整体的缩放
	// graph.value.translate(200, 40); // 图形相对画布的相对位置，平移
	// graph.value.centerContent(); // 将画布内容中心与视口中心对齐
});
</script>
 
<style scoped lang="scss"></style>